﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading;
using Microsoft.Win32.SafeHandles;
using JasLib.Extensions;

namespace JasLib.Interop.Win32
{
    /// <summary>
    /// </summary>
    /// <remarks>
    /// The A and W suffixes to function names don't exist in Windows XP SP3,
    /// but the undecorated original entry points used ANSI (strange but true) and remain accessible in Windows 7,
    /// so those are what we bind to. All new string-oriented ESENT functions have A and W variants
    /// without undecorated names.
    /// http://msdn.microsoft.com/en-us/library/gg294078(v=EXCHG.10).aspx
    /// </remarks>
    public static partial class ESENT
    {
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetAddColumn", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetAddColumn(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szColumnName,
            [In] ref JET_COLUMNDEF pcolumndef,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] byte[] pvDefault,
            [In] uint cbDefault,
            [Out] out JET_COLUMNID pcolumnid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetAttachDatabase", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetAttachDatabase(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szFilename,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetAttachDatabase2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetAttachDatabase2(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szFilename,
            [In] uint cpgDatabaseSizeMax,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetBackup", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetBackup(
            [In, MarshalAs(UnmanagedType.LPStr)] string szBackupPath,
            [In] JET_GRBIT grbit,
            [In] JET_PFNSTATUS pfnStatus);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetBackupInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetBackupInstance(
            [In] JET_INSTANCE instance,
            [In, MarshalAs(UnmanagedType.LPStr)] string szBackupPath,
            [In] JET_GRBIT grbit,
            [In] JET_PFNSTATUS pfnStatus);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetBeginExternalBackup", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetBeginExternalBackup([In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetBeginExternalBackupInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetBeginExternalBackupInstance(
            [In] JET_INSTANCE instance,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetBeginSession", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetBeginSession(
            [In] JET_INSTANCE instance,
            [Out] out JET_SESID psesid,
            [In] UINT_PTR szUserName,
            [In] UINT_PTR szPassword);

        /// <summary>
        /// Secure overload of the Win32 JetBeginSession function.
        /// </summary>
        public static JET_ERR JetBeginSession(
            JET_INSTANCE instance,
            out JET_SESID psesid,
            SecureString szUserName,
            SecureString szPassword)
        {
            UINT_PTR pszUserName = UINT_PTR.Zero;
            UINT_PTR pszPassword = UINT_PTR.Zero;
            try
            {
                if (szUserName != null)
                    pszUserName = Marshal.SecureStringToGlobalAllocUnicode(szUserName);
                if (szPassword != null)
                    pszPassword = Marshal.SecureStringToGlobalAllocUnicode(szPassword);

                return JetBeginSession(instance, out psesid, pszUserName, pszPassword);
            }
            finally
            {
                if (pszUserName != UINT_PTR.Zero)
                    Marshal.ZeroFreeGlobalAllocUnicode(pszUserName);
                if (pszPassword != UINT_PTR.Zero)
                    Marshal.ZeroFreeGlobalAllocUnicode(pszPassword);
            }
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetBeginTransaction", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetBeginTransaction([In] JET_SESID sesid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetBeginTransaction2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetBeginTransaction2(
            [In] JET_SESID sesid,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCloseDatabase", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCloseDatabase(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In] JET_GRBIT grbit = 0);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCloseFile", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCloseFile([In] JET_HANDLE hfFile);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCloseFileInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCloseFileInstance(
            [In] JET_INSTANCE instance,
            [In] JET_HANDLE hfFile);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCloseTable", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCloseTable(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCommitTransaction", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCommitTransaction(
            [In] JET_SESID sesid,
            [In] JET_GRBIT grbit);

        /// <param name="pconvert">
        /// A pointer used to designate an alternative ESE DLL that can be used to read the source database,
        /// and to provide optional parameters for a JetCompact operation that is converting a database from
        /// an earlier to a later version format. This feature was discontinued in Windows Server 2003. 
        /// </param>
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCompact", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCompact(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szDatabaseSrc,
            [In, MarshalAs(UnmanagedType.LPStr)] string szDatabaseDest,
            [In, MarshalAs(UnmanagedType.FunctionPtr)] JET_PFNSTATUS pfnStatus,
            [In] UINT_PTR pconvert,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetComputeStats", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetComputeStats(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCreateDatabase", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCreateDatabase(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szFilename,
            [In, MarshalAs(UnmanagedType.LPStr)] string szConnect,
            [Out] out JET_DBID pdbid,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCreateDatabase2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCreateDatabase2(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szFilename,
            [In] uint cpgDatabaseSizeMax,
            [Out] out JET_DBID pdbid,
            [In] JET_GRBIT grbit);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sesid"></param>
        /// <param name="tableid"></param>
        /// <param name="szIndexName"></param>
        /// <param name="grbit"></param>
        /// <param name="szKey"></param>
        /// <param name="cbKey">This is a count of bytes in the key string, including all null terminators.
        /// Do not confuse this with a count of characters as the documentation may indicate,
        /// or you will get access violations.</param>
        /// <param name="lDensity"></param>
        /// <returns></returns>
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCreateIndex", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCreateIndex(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szIndexName,
            [In] JET_GRBIT grbit,
            [In, MarshalAs(UnmanagedType.LPStr)] string szKey,
            [In] uint cbKey,
            [In] uint lDensity = 100);

        /// <summary>
        /// </summary>
        /// <remarks>
        /// From Esent.Interop: "This is important: only create one index at a time with JetCreateIndex2!
        /// The API takes an array of JET_INDEXCREATE objects, but if more than one
        /// index is passed in then the API operates in batch mode, which requires
        /// the caller NOT be in a transaction."
        /// </remarks>
        /// <param name="sesid"></param>
        /// <param name="tableid"></param>
        /// <param name="pindexcreate"></param>
        /// <param name="cIndexCreate"></param>
        /// <returns></returns>
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCreateIndex2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCreateIndex2(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] JET_INDEXCREATE[] pindexcreate,
            [In] uint cIndexCreate);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCreateInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCreateInstance(
            [Out] out JET_INSTANCE pinstance,
            [In, MarshalAs(UnmanagedType.LPStr)] string szInstanceName);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCreateInstance2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCreateInstance2(
            [Out] out JET_INSTANCE pinstance,
            [In, MarshalAs(UnmanagedType.LPStr)] string szInstanceName,
            [In, MarshalAs(UnmanagedType.LPStr)] string szDisplayName = null,
            [In] JET_GRBIT grbit = 0);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCreateTable", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCreateTable(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTableName,
            [In] uint lPages,
            [In] uint lDensity,
            [Out] out JET_TABLEID ptableid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCreateTableColumnIndex", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCreateTableColumnIndex(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, Out] ref JET_TABLECREATE ptablecreate);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCreateTableColumnIndex2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCreateTableColumnIndex2(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, Out] ref JET_TABLECREATE2 ptablecreate);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetCreateTableColumnIndex3W", ExactSpelling = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetCreateTableColumnIndex3(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, Out] ref JET_TABLECREATE3 ptablecreate);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDefragment", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDefragment(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTableName,
            [Out] out uint pcPasses,
            [Out] out uint pcSeconds,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDefragment2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDefragment2(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTableName,
            [Out] out uint pcPasses,
            [Out] out uint pcSeconds,
            [In] JET_CALLBACK callback,
            [In] JET_GRBIT grbit);

        /// <summary>
        /// This function does not exist yet, but for some reason Microsoft leaves an entry for it in the docs.
        /// </summary>
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDefragment3", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDefragment3();

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDelete", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDelete(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDeleteColumn", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDeleteColumn(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szColumnName);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDeleteColumn2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDeleteColumn2(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szColumnName,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDeleteIndex", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDeleteIndex(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szIndexName);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDeleteTable", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDeleteTable(
            [In] JET_SESID sesid,
            [In] JET_DBID tableid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTableName);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDetachDatabase", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDetachDatabase(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szFilename);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDetachDatabase2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDetachDatabase2(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szFilename,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDupCursor", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDupCursor(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out] out JET_TABLEID ptableid,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetDupSession", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetDupSession(
            [In] JET_SESID sesid,
            [Out] out JET_SESID psesid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetEnableMultiInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetEnableMultiInstance(
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] JET_SETSYSPARAM[] psetsysparam,
            [In] uint csetsysparam,
            [Out] out uint pcsetsucceed);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetEndExternalBackup", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetEndExternalBackup();

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetEndExternalBackupInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetEndExternalBackupInstance([In] JET_INSTANCE instance);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetEndExternalBackupInstance2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetEndExternalBackupInstance2(
            [In] JET_INSTANCE instance,
            [In] JET_GRBIT grbit);

        /// <summary>
        /// JetEndSession will close all tables and databases opened by the session.
        /// </summary>
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetEndSession", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetEndSession(
            [In] JET_SESID sesid,
            [In] JET_GRBIT grbit = 0);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetEnumerateColumns", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetEnumerateColumns(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] uint cEnumColumnId,
            [In] JET_ENUMCOLUMNID[] rgEnumColumnId,
            [Out] out uint pcEnumColumn,
            [Out] out UINT_PTR prgEnumColumn,
            [In] JET_PFNREALLOC pfnRealloc,
            [In] UINT_PTR pvReallocContext,
            [In] uint cbDataMost,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetEscrowUpdate", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetEscrowUpdate(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] JET_COLUMNID columnid,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] pv,
            [In] uint cbMax,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)] byte[] pvOld,
            [In] uint cbOldMax,
            [Out] out uint pcbOldActual,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetExternalRestore", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetExternalRestore(
            [In, MarshalAs(UnmanagedType.LPStr)] string szCheckpointFilePath,
            [In, MarshalAs(UnmanagedType.LPStr)] string szLogPath,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] JET_RSTMAP[] rgrstmap,
            [In] int crstfilemap,
            [In, MarshalAs(UnmanagedType.LPStr)] string szBackupLogPath,
            [In] int genLow,
            [In] int genHigh,
            [In] JET_PFNSTATUS pfn);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetExternalRestore2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetExternalRestore2(
            [In, MarshalAs(UnmanagedType.LPStr)] string szCheckpointFilePath,
            [In, MarshalAs(UnmanagedType.LPStr)] string szLogPath,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] JET_RSTMAP[] rgrstmap,
            [In] int crstfilemap,
            [In, MarshalAs(UnmanagedType.LPStr)] string szBackupLogPath,
            [In, Out] ref JET_LOGINFO pLogInfo,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTargetInstanceName,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTargetInstanceLogPath,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTargetInstanceCheckpointPath,
            [In] JET_PFNSTATUS pfn);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetFreeBuffer", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetFreeBuffer([In] UINT_PTR pbBuf);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetAttachInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetAttachInfo(
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] char[] szz,
            [In] uint cbMax,
            [Out] out uint pcbActual);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetAttachInfoInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetAttachInfoInstance(
            [In] JET_INSTANCE instance,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] char[] szz,
            [In] uint cbMax,
            [Out] out uint pcbActual);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetBookmark", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetBookmark(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] szz,
            [In] uint cbMax,
            [Out] out uint pcbActual);

        /// <summary>
        /// Safe overload of the Win32 JetGetBookmark function that throws an exception if it encounters an error.
        /// </summary>
        public static byte[] JetGetBookmark(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid)
        {
            JET_ERR errorCode;

            /// Get the size.
            uint uiActualSize;
            errorCode = JetGetBookmark(sesid, tableid, null, 0, out uiActualSize);
            if (errorCode == JET_ERR.JET_errNoCurrentRecord)
                return null;
            errorCode.TryThrowEsentException();

            /// Get the key itself.
            byte[] buffer = new byte[uiActualSize];
            errorCode = JetGetBookmark(sesid, tableid, buffer, uiActualSize, out uiActualSize);
            errorCode.TryThrowEsentException();

            return buffer;
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetColumnInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetColumnInfo(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTableName,
            [In, MarshalAs(UnmanagedType.LPStr)] string szColumnName,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] byte[] pvResult,
            [In] uint cbResult,
            [In] JetColumnInfoLevel InfoLevel);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetColumnInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetColumnInfo(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTableName,
            [In] ref JET_COLUMNID szColumnName,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] byte[] pvResult,
            [In] uint cbResult,
            [In] JetColumnInfoLevel InfoLevel);

        /// <summary>
        /// Simplified overload of the Win32 JetGetColumnInfo function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetGetColumnInfo(
            JET_SESID sesid,
            JET_DBID dbid,
            string szTableName,
            string szColumnName,
            out JET_COLUMNBASE columnDef)
        {
            columnDef = new JET_COLUMNBASE { cbStruct = MarshalHelper.SizeOf<JET_COLUMNBASE>() };
            byte[] buffer = columnDef.GetBytes();

            JET_ERR errorCode = JetGetColumnInfo(
                sesid,
                dbid,
                szTableName,
                szColumnName,
                buffer,
                (uint)buffer.Length,
                JetColumnInfoLevel.JET_ColInfoBase);
            errorCode.TryThrowEsentException();

            columnDef = buffer.FromBytes<JET_COLUMNBASE>();
            return;
        }

        /// <summary>
        /// Simplified overload of the Win32 JetGetColumnInfo function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetGetColumnInfo(
            JET_SESID sesid,
            JET_DBID dbid,
            string szTableName,
            JET_COLUMNID columnId,
            out JET_COLUMNBASE columnDef)
        {
            columnDef = new JET_COLUMNBASE { cbStruct = MarshalHelper.SizeOf<JET_COLUMNBASE>() };
            byte[] buffer = columnDef.GetBytes();

            JET_ERR errorCode = JetGetColumnInfo(
                sesid,
                dbid,
                szTableName,
                ref columnId,
                buffer,
                (uint)buffer.Length,
                JetColumnInfoLevel.JET_ColInfoBaseByColid);
            errorCode.TryThrowEsentException();

            columnDef = buffer.FromBytes<JET_COLUMNBASE>();
            return;
        }

        /// <summary>
        /// Simplified overload of the Win32 JetGetColumnInfo function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetGetColumnInfo(
            JET_SESID sesid,
            JET_DBID dbid,
            string szTableName,
            string szColumnName,
            out JET_COLUMNDEF columnDef)
        {
            columnDef = new JET_COLUMNDEF { cbStruct = MarshalHelper.SizeOf<JET_COLUMNDEF>() };
            byte[] buffer = columnDef.GetBytes();

            JET_ERR errorCode = JetGetColumnInfo(
                sesid,
                dbid,
                szTableName,
                szColumnName,
                buffer,
                (uint)buffer.Length,
                JetColumnInfoLevel.JET_ColInfo);
            errorCode.TryThrowEsentException();

            columnDef = buffer.FromBytes<JET_COLUMNDEF>();
            return;
        }

        /// <summary>
        /// Simplified overload of the Win32 JetGetColumnInfo function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetGetColumnInfo(
            JET_SESID sesid,
            JET_DBID dbid,
            string szTableName,
            JET_COLUMNID columnId,
            out JET_COLUMNDEF columnDef)
        {
            columnDef = new JET_COLUMNDEF { cbStruct = MarshalHelper.SizeOf<JET_COLUMNDEF>() };
            byte[] buffer = columnDef.GetBytes();

            JET_ERR errorCode = JetGetColumnInfo(
                sesid,
                dbid,
                szTableName,
                ref columnId,
                buffer,
                (uint)buffer.Length,
                JetColumnInfoLevel.JET_ColInfoByColid);
            errorCode.TryThrowEsentException();

            columnDef = buffer.FromBytes<JET_COLUMNDEF>();
            return;
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetCurrentIndex", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetCurrentIndex(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out] StringBuilder szIndexName,
            [In] uint cchIndexName);

        /// <summary>
        /// Safe overload of the Win32 JetGetCurrentIndex function that throws an exception if it encounters an error.
        /// </summary>
        public static string JetGetCurrentIndex(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid)
        {
            StringBuilder sb = new StringBuilder(Constants.JET_cbNameMost + 1);
            JET_ERR errorCode = JetGetCurrentIndex(sesid, tableid, sb, (uint)sb.Capacity);
            errorCode.TryThrowEsentException();
            return sb.ToString().TrimToNull();
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetCursorInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetCursorInfo(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvResult = null,
            [In] uint cbMax = 0,
            [In] JetCursorInfoLevel InfoLevel = 0);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetDatabaseFileInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetDatabaseFileInfo(
            [In, MarshalAs(UnmanagedType.LPStr)] string szDatabaseName,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pvResult,
            [In] uint cbMax,
            [In] JetDatabaseInfoLevel InfoLevel);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetDatabaseInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetDatabaseInfo(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvResult,
            [In] uint cbMax,
            [In] JetDatabaseInfoLevel InfoLevel);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetIndexInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetIndexInfo(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTableName,
            [In, MarshalAs(UnmanagedType.LPStr)] string szIndexName,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] byte[] pvResult,
            [In] uint cbResult,
            [In] JetIndexInfoLevel InfoLevel);

        /// <param name="paInstanceInfo">A pointer to a buffer which will receive the address of the first element of an array of structures.
        ///  The caller is responsible for freeing this memory with JetFreeBuffer.</param>
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetInstanceInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetInstanceInfo(
            [Out] out uint pcInstanceInfo,
            [Out] out UINT_PTR paInstanceInfo);

        /// <summary>
        /// Simplified overload of the Win32 JetGetInstanceInfo function that throws an exception if it encounters an error.
        /// </summary>
        public static JET_INSTANCE_INFO.Managed[] JetGetInstanceInfo()
        {
            List<JET_INSTANCE_INFO.Managed> managedInstances;
            JET_ERR errorCode;
            uint uiInstanceCount;
            UINT_PTR pBuffer;

            errorCode = ESENT.JetGetInstanceInfo(out uiInstanceCount, out pBuffer);
            errorCode.TryThrowEsentException();

            try
            {
                managedInstances = new List<JET_INSTANCE_INFO.Managed>((int)uiInstanceCount);

                JET_INSTANCE_INFO.Raw[] rawInstances = MarshalHelper.PtrToStructureArray<JET_INSTANCE_INFO.Raw>(pBuffer, (int)uiInstanceCount);
                foreach (JET_INSTANCE_INFO.Raw rawInstance in rawInstances)
                {
                    JET_INSTANCE_INFO.Managed managedInstance = new JET_INSTANCE_INFO.Managed
                    {
                        hInstanceId = rawInstance.hInstanceId,
                        szInstanceName = rawInstance.szInstanceName,
                        cDatabases = rawInstance.cDatabases,
                        szDatabaseDisplayName = MarshalHelper.PtrToStructureArray<UINT_PTR>(rawInstance.szDatabaseDisplayName, rawInstance.cDatabases).Select(ptr => Marshal.PtrToStringAnsi(ptr)).ToArray(),
                        szDatabaseFileName = MarshalHelper.PtrToStructureArray<UINT_PTR>(rawInstance.szDatabaseFileName, rawInstance.cDatabases).Select(ptr => Marshal.PtrToStringAnsi(ptr)).ToArray(),

                        /// SLVFileName isn't used, and the pointer always returns null.
                        szDatabaseSLVFileName = new string[0],
                        //szDatabaseSLVFileName = MarshalHelper.PtrToStructureArray<UINT_PTR>(rawInstance.szDatabaseSLVFileName, rawInstance.cDatabases).Select(ptr => Marshal.PtrToStringAnsi(ptr)).ToArray(),
                    };

                    managedInstances.Add(managedInstance);
                }
            }
            finally
            {
                if (pBuffer != UINT_PTR.Zero)
                {
                    errorCode = ESENT.JetFreeBuffer(pBuffer);
                    errorCode.TryThrowEsentException();
                }
            }

            return managedInstances.ToArray();
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetInstanceMiscInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetInstanceMiscInfo(
            [In] JET_INSTANCE instance,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pvResult,
            [In] uint cbMax,
            [In] JetInstanceMiscInfoLevel InfoLevel);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetLock", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetLock(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetLogInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetLogInfo(
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] char[] szz,
            [In] uint cbMax,
            [Out] out uint pcbActual);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetLogInfoInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetLogInfoInstance(
            [In] JET_INSTANCE instance,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] char[] szz,
            [In] uint cbMax,
            [Out] out uint pcbActual);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetLogInfoInstance2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetLogInfoInstance2(
            [In] JET_INSTANCE instance,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] char[] szz,
            [In] uint cbMax,
            [Out] out uint pcbActual,
            [In, Out] ref JET_LOGINFO pLogInfo);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetObjectInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetObjectInfo(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In] JET_OBJTYP objtyp,
            [In, MarshalAs(UnmanagedType.LPStr)] string szContainerName,
            [In, MarshalAs(UnmanagedType.LPStr)] string szObjectName,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)] byte[] pvResult,
            [In] uint cbMax,
            [In] JetObjectInfoLevel InfoLevel);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetRecordPosition", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetRecordPosition(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out] out JET_RECPOS precpos,
            [In] uint cbRecPos);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetRecordSize", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetRecordSize(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out] out JET_RECSIZE precpos,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetSecondaryIndexBookmark", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetSecondaryIndexBookmark(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSecondaryKey,
            [In] uint cbSecondaryKeyMax,
            [Out] out uint pcbSecondaryKeyActual,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)] byte[] pvPrimaryBookmark,
            [In] uint cbPrimaryBookmarkMax,
            [Out] out uint pcbPrimaryKeyActual,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetSystemParameter", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetSystemParameter(
            [In] JET_INSTANCE instance,
            [In] JET_SESID sesid,
            [In] JetSystemParameterCode paramid,
            [In, Out] ref UINT_PTR plParam,
            [Out] StringBuilder szParam,
            [In] uint cbMax);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetSystemParameter", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetSystemParameter(
            [In] JET_INSTANCE instance,
            [In] JET_SESID sesid,
            [In] JetSystemParameterCode paramid,
            [In, Out] UINT_PTR plParam,
            [Out] StringBuilder szParam,
            [In] uint cbMax);

        /// <summary>
        /// Simplified overload of the Win32 JetGetSystemParameter function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetGetSystemParameter(
            JET_INSTANCE instance,
            JET_SESID sesid,
            JetSystemParameterCode paramid,
            out string strParam,
            int iTryBufferLength = Constants.MAX_PATH)
        {
            UINT_PTR iValue = UINT_PTR.Zero;
            StringBuilder sb = new StringBuilder(iTryBufferLength + 1);
            JET_ERR errorCode = ESENT.JetGetSystemParameter(instance, sesid, paramid, ref iValue, sb, (uint)(sb.Capacity * sizeof(char)));
            errorCode.TryThrowEsentException();
            strParam = sb.ToString();
            return;
        }

        /// <summary>
        /// Simplified overload of the Win32 JetGetSystemParameter function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetGetSystemParameter(
            JET_INSTANCE instance,
            JET_SESID sesid,
            JetSystemParameterCode paramid,
            out UINT_PTR iParam)
        {
            iParam = UINT_PTR.Zero;
            JET_ERR errorCode = ESENT.JetGetSystemParameter(instance, sesid, paramid, ref iParam, null, 0);
            errorCode.TryThrowEsentException();
            return;
        }

        /// <summary>
        /// Simplified overload of the Win32 JetGetSystemParameter function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetGetSystemParameter(
            JET_INSTANCE instance,
            JET_SESID sesid,
            JetSystemParameterCode paramid,
            out int iParam)
        {
            UINT_PTR iValue;
            ESENT.JetGetSystemParameter(instance, sesid, paramid, out iValue);
            iParam = (int)iValue;
            return;
        }

        /// <summary>
        /// Simplified overload of the Win32 JetGetSystemParameter function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetGetSystemParameter(
            JET_INSTANCE instance,
            JET_SESID sesid,
            JetSystemParameterCode paramid,
            out bool bParam)
        {
            int iValue;
            ESENT.JetGetSystemParameter(instance, sesid, paramid, out iValue);
            bParam = (iValue != 0);
            return;
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetTableColumnInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetTableColumnInfo(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szColumnName,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] pvResult,
            [In] uint cbMax,
            [In] JetColumnInfoLevel InfoLevel);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetTableInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetTableInfo(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvResult,
            [In] uint cbMax,
            [In] JetTableInfoLevel InfoLevel);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetTableIndexInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetTableIndexInfo(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szIndexName,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] pvResult,
            [In] uint cbResult,
            [In] JetIndexInfoLevel InfoLevel);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetThreadStats", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetThreadStats(
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pvResult,
            [In] uint cbMax);

        /// <summary>
        /// Convenient overload of the Win32 JetGetThreadStats function that throws an exception if it encounters an error.
        /// </summary>
        public static JET_THREADSTATS JetGetThreadStats()
        {
            byte[] buffer = new byte[MarshalHelper.SizeOf<JET_THREADSTATS>()];
            JET_ERR result = JetGetThreadStats(buffer, (uint)buffer.Length);
            result.TryThrowEsentException();
            return buffer.FromBytes<JET_THREADSTATS>();
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetTruncateLogInfoInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetTruncateLogInfoInstance(
            [In] JET_INSTANCE instance,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] char[] szz,
            [In] uint cbMax,
            [Out] out uint pcbActual);

        /// <summary>
        /// Convenient overload of the Win32 JetGetTruncateLogInfoInstance function that throws an exception if it encounters an error.
        /// </summary>
        public static IEnumerable<string> JetGetTruncateLogInfoInstance(JET_INSTANCE instance, int iTryBufferLength = 1000)
        {
            char[] szz = new char[iTryBufferLength];
            uint uiActualUsedBufferLength;
            JET_ERR errorCode = JetGetTruncateLogInfoInstance(instance, szz, (uint)iTryBufferLength, out uiActualUsedBufferLength);
            errorCode.TryThrowEsentException();
            return InteropUtilities.SplitDoubleNullTerminated(szz, (int)uiActualUsedBufferLength);
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGetVersion", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGetVersion(
            [In] JET_SESID sesid,
            [Out] out uint pwVersion);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGotoBookmark", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGotoBookmark(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvBookmark,
            [In] uint cbBookmark);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGotoBookmark", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGotoPosition(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] ref JET_RECPOS precpos);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGotoSecondaryIndexBookmark", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGotoSecondaryIndexBookmark(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvSecondaryKey,
            [In] uint cbSecondaryKey,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)] byte[] pvPrimaryBookmark,
            [In] uint cbPrimaryBookmark,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetGrowDatabase", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetGrowDatabase(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In] uint cpg,
            [In] ref uint pcpgReal);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetIdle", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetIdle(
            [In] JET_SESID sesid,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetIndexRecordCount", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetIndexRecordCount(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out] out uint pcrec,
            [In] uint crecMax);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetInit", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetInit([In] ref JET_INSTANCE pinstance);

        [Obsolete]
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetInit2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetInit2(
            [In, Out] ref JET_INSTANCE pinstance,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetInit3", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetInit3(
            [In, Out] ref JET_INSTANCE pinstance,
            [In] ref JET_RSTINFO prstInfo,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetIntersectIndexes", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetIntersectIndexes(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] JET_INDEXRANGE[] rgindexrange,
            [In] uint cindexrange,
            [In, Out] ref JET_RECORDLIST precordlist,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetMakeKey", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetMakeKey(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvData,
            [In] uint cbData,
            [In] JET_GRBIT grbit);

        /// <summary>
        /// Simplified overload of the Win32 JetMakeKey function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetMakeKey(
            JET_SESID sesid,
            JET_TABLEID tableid,
            byte[] pvData,
            JET_GRBIT grbit)
        {
            JET_ERR errorCode = JetMakeKey(sesid, tableid, pvData, (uint)pvData.Length, grbit);
            errorCode.TryThrowEsentException();
            return;
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetMove", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetMove(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] int cRow,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOpenDatabase", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOpenDatabase(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szFilename,
            [In, MarshalAs(UnmanagedType.LPStr)] string szConnect,
            [Out] out JET_DBID pdbid,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOpenFile", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOpenFile(
            [In, MarshalAs(UnmanagedType.LPStr)] string szFileName,
            [Out] out JET_HANDLE phfFile,
            [Out] out uint pulFileSizeLow,
            [Out] out uint pulFileSizeHigh);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOpenFileInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOpenFileInstance(
            [In] JET_INSTANCE instance,
            [In, MarshalAs(UnmanagedType.LPStr)] string szFileName,
            [Out] out JET_HANDLE phfFile,
            [Out] out uint pulFileSizeLow,
            [Out] out uint pulFileSizeHigh);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOpenTable", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOpenTable(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTableName,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] pvParameters,
            [In] uint cbParameters,
            [In] JET_GRBIT grbit,
            [Out] out JET_TABLEID ptableid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOpenTemporaryTable", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOpenTemporaryTable(
            [In] JET_SESID sesid,
            [In] ref JET_OPENTEMPORARYTABLE popentemporarytable);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOpenTempTable", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOpenTempTable(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] JET_COLUMNDEF[] prgcolumndef,
            [In] uint ccolumn,
            [In] JET_GRBIT grbit,
            [Out] out JET_TABLEID ptableid,
            [Out] out JET_COLUMNID prgcolumnid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOpenTempTable2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOpenTempTable2(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] JET_COLUMNDEF[] prgcolumndef,
            [In] uint ccolumn,
            [In] LCID lcid,
            [In] JET_GRBIT grbit,
            [Out] out JET_TABLEID ptableid,
            [Out] out JET_COLUMNID prgcolumnid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOpenTempTable3", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOpenTempTable3(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] JET_COLUMNDEF[] prgcolumndef,
            [In] uint ccolumn,
            [In] ref JET_UNICODEINDEX pidxunicode,
            [In] JET_GRBIT grbit,
            [Out] out JET_TABLEID ptableid,
            [Out] out JET_COLUMNID prgcolumnid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOSSnapshotAbort", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOSSnapshotAbort(
            [In] JET_OSSNAPID snapId,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOSSnapshotEnd", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOSSnapshotEnd(
            [In] JET_OSSNAPID snapId,
            [In] JET_GRBIT grbit);

        /// <param name="paInstanceInfo">Pointer to an array of JET_INSTANCE_INFO which must be freed with JetFreeBuffer() when it is no longer needed.</param>
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOSSnapshotFreeze", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOSSnapshotFreeze(
            [In] JET_OSSNAPID snapId,
            [Out] out uint pcInstanceInfo,
            [Out] out UINT_PTR paInstanceInfo,
            [In] JET_GRBIT grbit);

        /// <param name="paInstanceInfo">Pointer to an array of JET_INSTANCE_INFO, one for each running instance,
        /// describing the instance and the databases that are part of it. This pointer must be freed with JetFreeBuffer.
        /// <param name="grbit"></param>
        /// <returns></returns>
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOSSnapshotGetFreezeInfo", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOSSnapshotGetFreezeInfo(
            [In] JET_OSSNAPID snapId,
            [Out] out uint pcInstanceInfo,
            [Out] out UINT_PTR paInstanceInfo,
            [In] JET_GRBIT grbit = 0);

        /// <summary>
        /// Simplified overload of the Win32 JetOSSnapshotGetFreezeInfo function that throws an exception if it encounters an error.
        /// </summary>
        public static JET_INSTANCE_INFO.Raw[] JetOSSnapshotGetFreezeInfo(
            JET_OSSNAPID snapId,
            JET_GRBIT grbit = 0)
        {
            uint cInstanceInfo;
            UINT_PTR aInstanceInfo;
            JET_ERR errorCode = JetOSSnapshotGetFreezeInfo(snapId, out cInstanceInfo, out aInstanceInfo, grbit);
            errorCode.TryThrowEsentException();

            JET_INSTANCE_INFO.Raw[] infos;
            try
            {
                infos = MarshalHelper.PtrToStructureArray<JET_INSTANCE_INFO.Raw>(aInstanceInfo, (int)cInstanceInfo);
            }
            finally
            {
                JetFreeBuffer(aInstanceInfo);
            }
            return infos;
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOSSnapshotPrepare", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOSSnapshotPrepare(
            [Out] out JET_OSSNAPID psnapId,
            [In] JET_GRBIT grbit = 0);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOSSnapshotPrepareInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOSSnapshotPrepareInstance(
            [In] JET_OSSNAPID psnapId,
            [In] JET_INSTANCE instance,
            [In] JET_GRBIT grbit = 0);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOSSnapshotTruncateLog", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOSSnapshotTruncateLog(
            [In] JET_OSSNAPID psnapId,
            [In] JET_GRBIT grbit = 0);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOSSnapshotTruncateLogInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOSSnapshotTruncateLogInstance(
            [In] JET_OSSNAPID psnapId,
            [In] JET_INSTANCE instance,
            [In] JET_GRBIT grbit = 0);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetOSSnapshotThaw", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetOSSnapshotThaw(
            [In] JET_OSSNAPID snapId,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetPrepareUpdate", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetPrepareUpdate(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] JetPrepareUpdateCode prep);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetReadFile", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetReadFile(
            [In] JET_HANDLE hfFile,
            [Out] out UINT_PTR pv,
            [In] uint cb,
            [Out] out uint pcbActual);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetReadFileInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetReadFileInstance(
            [In] JET_INSTANCE instance,
            [In] JET_HANDLE hfFile,
            [Out] out UINT_PTR pv,
            [In] uint cb,
            [Out] out uint pcbActual);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetRegisterCallback", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetRegisterCallback(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] JET_CBTYP cbtyp,
            [In] JET_CALLBACK pCallback,
            [In] UINT_PTR pvContext,
            [Out] out JET_HANDLE phCallbackId);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetRenameColumn", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetRenameColumn(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szName,
            [In, MarshalAs(UnmanagedType.LPStr)] string szNameNew,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetRenameTable", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetRenameTable(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szName,
            [In, MarshalAs(UnmanagedType.LPStr)] string szNameNew);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetResetSessionContext", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetResetSessionContext([In] JET_SESID sesid);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetResetTableSequential", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetResetTableSequential(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetRestore", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetRestore(
            [In, MarshalAs(UnmanagedType.LPStr)] string sz,
            [In] JET_PFNSTATUS pfn);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetRestore2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetRestore2(
            [In, MarshalAs(UnmanagedType.LPStr)] string sz,
            [In, MarshalAs(UnmanagedType.LPStr)] string szDest,
            [In] JET_PFNSTATUS pfn);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetRestoreInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetRestoreInstance(
            [In] JET_INSTANCE instance,
            [In, MarshalAs(UnmanagedType.LPStr)] string sz,
            [In, MarshalAs(UnmanagedType.LPStr)] string szDest,
            [In] JET_PFNSTATUS pfn);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetRetrieveColumn", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetRetrieveColumn(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] JET_COLUMNID columnid,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] pvData,
            [In] uint cbData,
            [Out] out uint pcbActual,
            [In] JET_GRBIT grbit,
            [In, Out] ref JET_RETINFO pretinfo);

        /// <summary>
        /// Simplified overload of the Win32 JetRetrieveColumn function that throws an exception
        /// if it encounters a non-ESENT error.
        /// </summary>
        public static JET_ERR JetRetrieveColumn(
            JET_SESID sesid,
            JET_TABLEID tableid,
            JET_COLUMNID columnid,
            out byte[] pvData)
        {
            pvData = null;
            JET_ERR errorCode;

            JET_RETINFO retInfo = new JET_RETINFO
            {
                cbStruct = MarshalHelper.SizeOf<JET_RETINFO>(),
                itagSequence = 1,
                ibLongValue = 0,
            };

            uint uiValueSize;
            errorCode = JetRetrieveColumn(sesid, tableid, columnid,
                null, 0, out uiValueSize, JET_GRBIT.JET_bitRetrieveCopy, ref retInfo);
            if (errorCode < 0)
                return errorCode;

            pvData = new byte[uiValueSize];

            errorCode = JetRetrieveColumn(sesid, tableid, columnid,
                pvData, (uint)pvData.Length, out uiValueSize, JET_GRBIT.JET_bitRetrieveCopy, ref retInfo);
            if (errorCode < 0)
                return errorCode;

            /// Might include a warning code.
            return errorCode;
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetRetrieveColumns", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetRetrieveColumns(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] JET_RETRIEVECOLUMN[] pretrievecolumn,
            [In] uint cretrievecolumn);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetRetrieveKey", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetRetrieveKey(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvData,
            [In] uint cbMax,
            [Out] out uint pcbActual,
            [In] JET_GRBIT grbit);

        /// <summary>
        /// Safe overload of the Win32 JetRetrieveKey function that throws an exception if it encounters an error.
        /// </summary>
        public static byte[] JetRetrieveKey(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid)
        {
            JET_ERR errorCode;

            /// Get the size.
            uint uiKeySize;
            errorCode = JetRetrieveKey(sesid, tableid, null, 0, out uiKeySize, JET_GRBIT.JET_bitRetrieveCopy);
            if (errorCode == JET_ERR.JET_errKeyNotMade)
                return null;
            errorCode.TryThrowEsentException();

            /// Get the key itself.
            byte[] buffer = new byte[uiKeySize];
            errorCode = JetRetrieveKey(sesid, tableid, buffer, uiKeySize, out uiKeySize, JET_GRBIT.JET_bitRetrieveCopy);
            errorCode.TryThrowEsentException();

            return buffer;
        }

        /// <summary>
        /// JetRollback will close all tables opened inside of the transaction but JetCommit will not.
        /// </summary>
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetRollback", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetRollback(
            [In] JET_SESID sesid,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSeek", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSeek(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetColumn", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetColumn(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] JET_COLUMNID columnid,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] pvData,
            [In] uint cbData,
            [In] JET_GRBIT grbit,
            [In] ref JET_SETINFO psetinfo);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetColumnDefaultValue", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetColumnDefaultValue(
            [In] JET_SESID sesid,
            [In] JET_DBID dbid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szTableName,
            [In, MarshalAs(UnmanagedType.LPStr)] string szColumnName,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] byte[] pvData,
            [In] uint cbData,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetColumns", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetColumns(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] JET_SETCOLUMN[] psetcolumn,
            [In] uint csetcolumn);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetCurrentIndex", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetCurrentIndex(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableidSrc,
            [In, MarshalAs(UnmanagedType.LPStr)] string szIndexName = null);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetCurrentIndex2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetCurrentIndex2(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableidSrc,
            [In, MarshalAs(UnmanagedType.LPStr)] string szIndexName,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetCurrentIndex3", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetCurrentIndex3(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableidSrc,
            [In, MarshalAs(UnmanagedType.LPStr)] string szIndexName,
            [In] JET_GRBIT grbit,
            [In] uint itagSequence);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetCurrentIndex4", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetCurrentIndex4(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableidSrc,
            [In, MarshalAs(UnmanagedType.LPStr)] string szIndexName,
            [In] ref JET_INDEXID pindexid,
            [In] JET_GRBIT grbit,
            [In] uint itagSequence);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetDatabaseSize", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetDatabaseSize(
            [In] JET_SESID sesid,
            [In, MarshalAs(UnmanagedType.LPStr)] string szDatabaseName,
            [In] uint cpg,
            [Out] out uint pcpgReal);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetIndexRange", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetIndexRange(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableidSrc,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetLS", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetLS(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] JET_LS ls,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetSessionContext", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetSessionContext(
            [In] JET_SESID sesid,
            [In] UINT_PTR ulContext);

        /// <param name="pinstance">Even though this is technically an out parameter, this API never modifies the contents of the provided buffer.</param>
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetSystemParameter", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetSystemParameter(
            [In] ref JET_INSTANCE pinstance,
            [In] JET_SESID sesid,
            [In] JetSystemParameterCode paramid,
            [In] UINT_PTR lParam,
            [In, MarshalAs(UnmanagedType.LPStr)] string szParam);

        /// <summary>
        /// Simplified overload of the Win32 JetSetSystemParameter function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetSetSystemParameter(
            JET_INSTANCE instance,
            JET_SESID sesid,
            JetSystemParameterCode paramid,
            string strParam)
        {
            JET_ERR errorCode = JetSetSystemParameter(ref instance, sesid, paramid, UINT_PTR.Zero, strParam);
            errorCode.TryThrowEsentException();
            return;
        }

        /// <summary>
        /// Simplified overload of the Win32 JetSetSystemParameter function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetSetSystemParameter(
            JET_INSTANCE instance,
            JET_SESID sesid,
            JetSystemParameterCode paramid,
            UINT_PTR iParam)
        {
            JET_ERR errorCode = JetSetSystemParameter(ref instance, sesid, paramid, iParam, null);
            errorCode.TryThrowEsentException();
            return;
        }

        /// <summary>
        /// Simplified overload of the Win32 JetSetSystemParameter function that throws an exception if it encounters an error.
        /// </summary>
        public static void JetSetSystemParameter(
            JET_INSTANCE instance,
            JET_SESID sesid,
            JetSystemParameterCode paramid,
            bool bParam)
        {
            JET_ERR errorCode = JetSetSystemParameter(ref instance, sesid, paramid, (bParam ? 1 : 0), null);
            errorCode.TryThrowEsentException();
            return;
        }

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetSetTableSequential", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetSetTableSequential(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableidSrc,
            [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetStopBackup", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetStopBackup();

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetStopBackupInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetStopBackupInstance([In] JET_INSTANCE instance);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetStopService", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetStopService();

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetStopServiceInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetStopServiceInstance();

        /// <summary>
        /// JetTerm can close all sessions, tables and databases opened by the instance.
        /// </summary>
        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetTerm", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetTerm([In] JET_INSTANCE instance);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetTerm2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetTerm2([In] JET_INSTANCE instance, [In] JET_GRBIT grbit);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetTruncateLog", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetTruncateLog();

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetTruncateLogInstance", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetTruncateLogInstance([In] JET_INSTANCE instance);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetUnregisterCallback", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetUnregisterCallback(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [In] JET_CBTYP cbtyp,
            [In] JET_HANDLE hCallbackId);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetUpdate", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetUpdate(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvBookmark,
            [In] uint cbBookmark,
            [Out] out uint pcbActual);

        [DllImport(Constants.ModuleNames.ESENT, EntryPoint = "JetUpdate2", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
        public static extern JET_ERR JetUpdate2(
            [In] JET_SESID sesid,
            [In] JET_TABLEID tableid,
            [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pvBookmark,
            [In] uint cbBookmark,
            [Out] out uint pcbActual,
            [In] JET_GRBIT grbit = 0);
    }
}